package com.atlzk.renting.user.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.aliyuncs.exceptions.ClientException;
import com.atlzk.common.entity.user.UserEntity;
import com.atlzk.common.utils.PageUtils;
import com.atlzk.common.utils.Query;
import com.atlzk.common.utils.R;
import com.atlzk.common.utils.RandomUtil;
import com.atlzk.renting.user.MQ.MQConfig;
import com.atlzk.renting.user.dao.UserDao;
import com.atlzk.renting.user.service.UserService;
import com.atlzk.renting.user.utils.SendSmsUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


@Service("userService")
public class UserServiceImpl extends ServiceImpl <UserDao, UserEntity> implements UserService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private SendSmsUtil sendSmsUtil;

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Value("${spring.mail.username}")
    private String setFrom;

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage <UserEntity> page = this.page(
                new Query<UserEntity>().getPage(params),
                new QueryWrapper<UserEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 登录
     * @param userEntity
     * @return
     */
    @Override
    public R login(UserEntity userEntity) {
        //1、获取登录 账户
        String loginName = userEntity.getLoginName();

        //邮箱
        if (loginName.matches("^\\w+@(\\w+\\.)+\\w+$")){
            UserEntity email = baseMapper.selectOne(new QueryWrapper <UserEntity>().eq("email", loginName));
            if (ObjectUtil.isNotNull(email) && matches(userEntity.getPassword(),email.getPassword())) {
                return R.ok("邮箱登录成功").put("user",email);
            }
        }
        //手机号
        else if (loginName.matches("^0{0,1}1[3456789][0-9]{9}$")){
            UserEntity telephone = baseMapper.selectOne(new QueryWrapper <UserEntity>().eq("telephone", loginName));
            if (ObjectUtil.isNotNull(telephone)  && matches(userEntity.getPassword(),telephone.getPassword())) {
                return R.ok("手机号登录成功").put("user",telephone);
            }
        }
        //账户
        else{
            UserEntity nickname = baseMapper.selectOne(new QueryWrapper <UserEntity>().eq("nickname", loginName));
            if (ObjectUtil.isNotNull(nickname)  && matches(userEntity.getPassword(),nickname.getPassword())) {
                return R.ok("账号登录成功").put("user",nickname);
            }
        }
        return R.error("登录失败");
    }

    /**
     * 加密密码比较
     * @param pwd1
     * @param pwd2
     * @return
     */
    public boolean matches(String pwd1, String pwd2) {
        return  encoder.matches(pwd1, pwd2);
    }

    /**
     * 发送验证码
     * @param telephoneOrEmail
     * @return
     */
    @Override
    public R sendCode(String telephoneOrEmail) {
        //1、获取验证码
        String code = RandomUtil.getRandom(6);
        HashMap <String, String> map = new HashMap <>();
        map.put("telephoneOrEmail", telephoneOrEmail);
        map.put("code", code);
        try {
            rabbitTemplate.convertAndSend(MQConfig.USER_QUEUE, map);
            return R.ok("加入队列");
        } catch (AmqpException e) {
            e.printStackTrace();
        }
        return R.error("发送短信失败");
    }

    /**
     * 发送短信或者邮件
     * @param telephoneOrEmail
     * @param code
     * @return
     */
    public String sendCodeForTelOrEmail(String telephoneOrEmail, String code) {
        //邮箱
        if (telephoneOrEmail.matches("^\\w+@(\\w+\\.)+\\w+$")){
            try{
                //验证码存于redis
                redisTemplate.opsForValue().set("email"+telephoneOrEmail,code,5, TimeUnit.MINUTES);
                MimeMessage message = javaMailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message,true,"UTF-8");

                String text = "【华烨找房】：验证码为：" + code+ "，请尽快操作，务将此验证码交与别人";

                helper.setFrom(setFrom);
                helper.setSubject("验证");
                helper.setTo(telephoneOrEmail);
                helper.setText(text);
                helper.setSentDate(new Date());

                javaMailSender.send(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //手机号 短信发送
        else if (telephoneOrEmail.matches("^0{0,1}1[3456789][0-9]{9}$")){
            try {
                //验证码存于redis
                redisTemplate.opsForValue().set("tel"+telephoneOrEmail,code,5, TimeUnit.MINUTES);
                sendSmsUtil.sendMsg(telephoneOrEmail, code);
                System.out.println("手机号："+telephoneOrEmail+",验证码："+code+",验证码发送成功");
                return "短信验证码成功";
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }
        return "验证码发送失败";
    }

    /**
     * 注册
     * @param userEntity
     * @return
     */
    @Override
    public R register(UserEntity userEntity) {
        try {
            if(!userEntity.getEmail().matches("^\\w+@(\\w+\\.)+\\w+$")){
                return R.ok("邮箱错误");
            }
            if (!userEntity.getTelephone().matches("^0{0,1}1[3456789][0-9]{9}$")){
                return R.ok("手机号错误");
            }
            userEntity.setPassword(encoder.encode(userEntity.getPassword()));
            userEntity.setRegisterDate(new Date());
            baseMapper.insert(userEntity);
            return R.ok("创建成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.ok("创建失败");
    }

    /**
     * 验证码登录
     */
    @Override
    public R loginCode(String telephoneOrEmail, String code) {
        if (telephoneOrEmail.matches("^\\w+@(\\w+\\.)+\\w+$")) {
            String code_redis = (String) redisTemplate.opsForValue().get("email" + telephoneOrEmail);
            if (code.equals(code_redis)) {
                return R.ok("邮箱验证码登录成功");
            }
        }
        if (telephoneOrEmail.matches("^0{0,1}1[3456789][0-9]{9}$")) {
            String code_redis = (String) redisTemplate.opsForValue().get("tel" + telephoneOrEmail);
            if (code.equals(code_redis)) {
                return R.ok("短信验证码登录成功");
            }
        }
        return R.error("验证码错误，登录失败");
    }

    /**
     * 根据手机号 邮箱 用户名  查询用户信息
     * @param userNum
     * @return
     */
    @Override
    public R findOne(String userNum) {
        UserEntity userEntity = new UserEntity();
        //邮箱验证
        if (userNum.matches("^\\w+@(\\w+\\.)+\\w+$")){
            UserEntity eamil = baseMapper.selectOne(new QueryWrapper <UserEntity>().eq("email", userNum));
            userEntity = eamil;
        }
        //手机号验证
        if (userNum.matches("^0{0,1}1[3456789][0-9]{9}$")) {
            UserEntity telephone = baseMapper.selectOne(new QueryWrapper <UserEntity>().eq("telephone", userNum));
            userEntity = telephone;

        }
        if (ObjectUtil.isEmpty(userEntity.getId())) {
            UserEntity nickname = baseMapper.selectOne(new QueryWrapper <UserEntity>().eq("nickname", userNum));
            userEntity = nickname;
        }
        return R.ok().put("user",userEntity);


    }


}